import pygame
import math
import random
from pygame.locals import *

# 初始化 Pygame
pygame.init()

# 设置窗口参数
WIDTH, HEIGHT = 600, 600
screen = pygame.display.set_mode((WIDTH, HEIGHT))
clock = pygame.time.Clock()

# 颜色定义
WHITE = (255, 255, 255)
RED = (255, 0, 0)
BLUE = (0, 0, 255)

# 物理参数
gravity = 0.2  # 重力加速度
friction = 0.99  # 摩擦力
rotation_speed = 0.02  # 六边形旋转速度
ball_radius = 10
hex_radius = 200


# 计算六边形顶点
def get_hexagon_vertices(center, radius, angle):
    vertices = []
    for i in range(6):
        theta = math.radians(60 * i) + angle
        x = center[0] + radius * math.cos(theta)
        y = center[1] + radius * math.sin(theta)
        vertices.append((x, y))
    return vertices


# 反弹计算
def reflect(velocity, normal):
    dot_product = velocity[0] * normal[0] + velocity[1] * normal[1]
    return (
        velocity[0] - 2 * dot_product * normal[0],
        velocity[1] - 2 * dot_product * normal[1]
    )


# 球类
class Ball:
    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.vx = random.uniform(-2, 2)
        self.vy = random.uniform(-2, 2)

    def update(self, hex_vertices, hex_center, rotation_angle):
        # 更新速度
        self.vy += gravity
        self.vx *= friction
        self.vy *= friction

        # 更新位置
        self.x += self.vx
        self.y += self.vy

        # 检测和六边形壁的碰撞
        for i in range(6):
            p1 = hex_vertices[i]
            p2 = hex_vertices[(i + 1) % 6]
            edge_vec = (p2[0] - p1[0], p2[1] - p1[1])
            edge_normal = (-edge_vec[1], edge_vec[0])
            edge_length = math.sqrt(edge_normal[0] ** 2 + edge_normal[1] ** 2)
            edge_normal = (edge_normal[0] / edge_length, edge_normal[1] / edge_length)

            # 计算球到边的投影
            ball_vec = (self.x - p1[0], self.y - p1[1])
            projection = ball_vec[0] * edge_normal[0] + ball_vec[1] * edge_normal[1]

            if projection < ball_radius:  # 发生碰撞
                self.vx, self.vy = reflect((self.vx, self.vy), edge_normal)
                self.x += edge_normal[0] * (ball_radius - projection)
                self.y += edge_normal[1] * (ball_radius - projection)

    def draw(self, screen):
        pygame.draw.circle(screen, RED, (int(self.x), int(self.y)), ball_radius)


# 主循环
running = True
rotation_angle = 0
ball = Ball(WIDTH // 2, HEIGHT // 2)
while running:
    screen.fill(WHITE)
    for event in pygame.event.get():
        if event.type == QUIT:
            running = False

    # 旋转六边形
    rotation_angle += rotation_speed
    hex_vertices = get_hexagon_vertices((WIDTH // 2, HEIGHT // 2), hex_radius, rotation_angle)

    # 更新球的位置
    ball.update(hex_vertices, (WIDTH // 2, HEIGHT // 2), rotation_angle)

    # 绘制六边形
    pygame.draw.polygon(screen, BLUE, hex_vertices, 2)

    # 绘制球
    ball.draw(screen)

    pygame.display.flip()
    clock.tick(60)

pygame.quit()
